package valid

import (
	"fmt"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	zhTranslations "github.com/go-playground/validator/v10/translations/zh"
	"github.com/vueadmin/global"
	"github.com/vueadmin/pkg/captcha"
	"github.com/vueadmin/utils/conv"
	"reflect"
	"regexp"
)

var (
	Validate *validator.Validate
	Trans    ut.Translator
)

// 启动时注册翻译器
func InitValidator() *validator.Validate {
	zh_ch := zh.New()
	Validate = validator.New()
	//注册一个函数，获取struct tag里自定义的label作为字段名
	Validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
		name := fld.Tag.Get("label")
		return name
	})

	uni := ut.New(zh_ch)
	Trans, _ = uni.GetTranslator("zh")
	//验证器注册翻译器
	zhTranslations.RegisterDefaultTranslations(Validate, Trans)

	//手机号验证
	Validate.RegisterValidation("mobile", mobileValidion)
	Validate.RegisterTranslation("mobile", Trans, translateMobileFunc, translateMobileFuncFallback)

	//正则验证
	Validate.RegisterValidation("regex", regexValidion)
	Validate.RegisterTranslation("regex", Trans, translateRegexFunc, translateRegexFuncFallback)

	//唯一值验证
	Validate.RegisterValidation("unique", uniqueValidion)
	Validate.RegisterTranslation("unique", Trans, translateUniqueFunc, translateUniqueFuncFallback)

	//金额验证
	Validate.RegisterValidation("amount", amountValidion)
	Validate.RegisterTranslation("amount", Trans, translateAmountFunc, translateAmountFuncFallback)

	//身份证号验证
	Validate.RegisterValidation("idcard", idValidion)
	Validate.RegisterTranslation("idcard", Trans, translateIdFunc, translateIdFuncFallback)

	//相同值验证
	Validate.RegisterValidation("same", sameValidion)
	Validate.RegisterTranslation("same", Trans, translateSameFunc, translateSameFuncFallback)

	//图片验证码验证
	Validate.RegisterValidation("captcha", captchaValidion)
	Validate.RegisterTranslation("captcha", Trans, translateCaptchaFunc, translateCaptchaFuncFallback)

	return Validate
}

// 金额验证
func amountValidion(fl validator.FieldLevel) bool {
	return fl.Field().Float() > 0
}

func translateAmountFunc(ut ut.Translator) error {
	return ut.Add("regex", "{0}格式错误!", true)
}

func translateAmountFuncFallback(ut ut.Translator, fe validator.FieldError) string {
	t, _ := ut.T("regex", fe.Field())
	return t
}

// 验证码验证
func captchaValidion(fl validator.FieldLevel) bool {
	return captcha.Verify(fl.Parent().FieldByName("CaptchaId").String(), fl.Field().String())
}

func translateCaptchaFunc(ut ut.Translator) error {
	return ut.Add("captcha", "验证码输入错误!", true)
}

func translateCaptchaFuncFallback(ut ut.Translator, fe validator.FieldError) string {
	t, _ := ut.T("captcha", fe.Field())
	return t
}

// 身份证号验证
func idValidion(fl validator.FieldLevel) bool {
	field := fl.Field()
	switch field.Kind() {
	case reflect.String:
		re, err := regexp.Compile(`^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
		if err != nil {
			return false
		}
		return re.MatchString(field.String())
	default:
		return false
	}
}

func translateIdFunc(ut ut.Translator) error {
	return ut.Add("idcard", "{0}格式错误!", true)
}

func translateIdFuncFallback(ut ut.Translator, fe validator.FieldError) string {
	t, _ := ut.T("idcard", fe.Field())
	return t
}

// 手机号验证
func mobileValidion(fl validator.FieldLevel) bool {
	field := fl.Field()
	switch field.Kind() {
	case reflect.String:
		re, err := regexp.Compile(`^1[3456789]\d{9}$`)
		if err != nil {
			return false
		}
		return re.MatchString(field.String())
	default:
		return false
	}
}

func translateMobileFunc(ut ut.Translator) error {
	return ut.Add("mobile", "{0}格式错误!", true)
}

func translateMobileFuncFallback(ut ut.Translator, fe validator.FieldError) string {
	t, _ := ut.T("mobile", fe.Field())
	return t
}

// 正则验证
func regexValidion(fl validator.FieldLevel) bool {
	field := fl.Field()
	fieldName, _ := fl.Parent().Type().FieldByName(fl.StructFieldName())

	re, err := regexp.Compile(fieldName.Tag.Get("rule"))
	if err != nil {
		return false
	}
	return re.MatchString(field.String())
}

func translateRegexFunc(ut ut.Translator) error {
	return ut.Add("regex", "{0}格式错误!", true)
}

func translateRegexFuncFallback(ut ut.Translator, fe validator.FieldError) string {
	t, _ := ut.T("regex", fe.Field())
	return t
}

// 相同值验证
func sameValidion(fl validator.FieldLevel) bool {
	field := fl.Field()
	fieldName, _ := fl.Parent().Type().FieldByName(fl.StructFieldName())
	tag := fieldName.Tag.Get("target")
	return field.String() == fl.Parent().FieldByName(tag).String()
}

func translateSameFunc(ut ut.Translator) error {
	return ut.Add("same", "{0}输入不一致!", true)
}

func translateSameFuncFallback(ut ut.Translator, fe validator.FieldError) string {
	t, _ := ut.T("same", fe.Field())
	return t
}

// 唯一值验证
func uniqueValidion(fl validator.FieldLevel) bool {
	var count int64
	fieldName, _ := fl.Parent().Type().FieldByName(fl.StructFieldName())
	table := fieldName.Tag.Get("table")

	array := conv.StringToSlice(table, ":")
	query := global.DB.Table(global.CONF.Db.Prefix + array[0])
	if len(array) > 1 {
		pk, _ := fl.Parent().Type().FieldByName(array[1])
		query = query.Where(fmt.Sprintf("%s !=%d", pk.Tag.Get("json"), fl.Parent().FieldByName(array[1])))
	}
	if err := query.Where(fieldName.Tag.Get("json"), fl.Field().Interface()).Count(&count).Error; err != nil {
		panic(err)
	}
	if count > 0 {
		return false
	}
	return true
}

func translateUniqueFunc(ut ut.Translator) error {
	return ut.Add("unique", "{0}已存在!", true)
}

func translateUniqueFuncFallback(ut ut.Translator, fe validator.FieldError) string {
	t, _ := ut.T("unique", fe.Field())
	return t
}
